(import
 (chezscheme)
 (glfw glfw)
 (gl constant)
 (gl gl))

(define-syntax define-callback
  (syntax-rules ()
     ((_ () return-type p)
      (let ((code (foreign-callable __collect_safe p () return-type)))
	(lock-object code)
	(foreign-callable-entry-point code)))
     ((_ (parameter-types ...) return-type p)
      (let ((code (foreign-callable __collect_safe p (parameter-types ...) return-type)))
     	(lock-object code)
     	(foreign-callable-entry-point code)))))

(define (error-callback error description)
  (display (format "Error: ~D ~A\n" error description))
  (flush-output-port))

(define (process-input window)
  (when (= (glfwGetKey window GLFW_KEY_ESCAPE) GLFW_PRESS)
    (glfwSetWindowShouldClose window GLFW_TRUE)
    (display "close window.\n")
    (flush-output-port)))


(define (show window)
  (do () ((= (glfwWindowShouldClose window) GLFW_TRUE)
	  (display "terminate.\n")
	  (flush-output-port)
	  (glfwTerminate))
    (let ((red (/ (random 11) 10.0))
	  (green (/ (random 11) 10.0))
	  (blue (/ (random 11) 10.0)))
      ;; (display (format "show triangle(~A ~A)\n" window (current-time)))
      (gl-clear-color 0.0 0.0 0.0 1.0)
      (gl-clear GL_COLOR_BUFFER_BIT)

      (gl-begin GL_TRIANGLES)

      (gl-color3f 1.0 0.0 0.0)
      (gl-vertex3f 0.0 1.0 0.0)

      (gl-color3f 0.0 1.0 0.0)
      (gl-vertex3f -1.0 -1.0 0.0)

      (gl-color3f 0.0 0.0 1.0)
      (gl-vertex3f 1.0 -1.0 0.0)

      (gl-end)
      (process-input window)
      (glfwSwapBuffers window)
      (glfwPollEvents)
      (sleep (make-time 'time-duration 100000000 0))
      ))
  )

(define (app)
  (glfwSetErrorCallback (define-callback (int string) void error-callback))
  (display (format "~A\n" (glfwGetVersionString)))
  (when (not (glfwInit))
    (display "failed to init.\n")
    (exit -1))
  (display "init successfully.\n")
  ;; (glfw-window-hint GLFW_CONTEXT_VERSION_MAJOR 3)
  ;; (glfw-window-hint GLFW_CONTEXT_VERSION_MINOR 2)
  ;; (glfw-window-hint GLFW_OPENGL_PROFILE GLFW_OPENGL_CORE_PROFILE)

  (let ((window (glfwCreateWindow 480 320 "Hello World"
				    0
				    0)))
    (when (not window)
      (display "failed to create window.\n")
      (glfwTerminate)
      (exit -1))
    (display (format "create window successfully.\n"))
    (glfwMakeContextCurrent window)
    (show window)
    )
  )

(app)
